package com.mjk.common.tools.excel.impl;


import com.mjk.common.base.model.BaseEntity;
import com.mjk.common.tools.excel.IFileImportAndExport;
import com.mjk.common.tools.excel.annotation.ExportFiled;
import com.mjk.common.tools.logger.BizLogger;
import com.mjk.common.util.*;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.csv.CSVRecord;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.util.CollectionUtils;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.Map.Entry;

/**
 * CSV 文件导入导出操作
 * @author Administrator
 *
 */
public class CsvImportAndExportImpl implements IFileImportAndExport {
	private CSVPrinter csvPrinter;
	private OutputStreamWriter osw ;
	@Override
	public <T extends BaseEntity> List<T> importFile(Class<T> clazz, InputStream xls, String encode) {
		try {
			Reader reader = new InputStreamReader(xls,encode);
			CSVParser parser = CSVFormat.EXCEL.withFirstRecordAsHeader().parse(reader);
			List<T> result = new ArrayList<>();
			Map<String,String> headerMapping = getExportFieldMap(clazz);
			for (CSVRecord cRecord : parser.getRecords()) {
				T t = clazz.newInstance();
				for(Entry<String, Integer> entry:parser.getHeaderMap().entrySet() ) {
					String name = MapUtils.getString(headerMapping, entry.getKey());
					if(ObjectUtils.isEmpty(name)) {
						name = entry.getKey();
					}
					Object value = ConvertUtils.convert(cRecord.get(entry.getKey()),ReflectionUtils.getField(clazz, name).getType());
					ReflectionUtils.setFieldValue(t,name,value);
				}
				result.add(t);
				BizLogger.info(t);
			}
			return result;
		}catch(Exception e) {
			return Collections.emptyList();
		}
	}

	@Override
	public <T extends BaseEntity> void exportFile(List<T> info,String filePath) {
		if (CollectionUtils.isEmpty(info)) {
			BizLogger.error("info is empty");
			return;
		}
		T t = info.get(0);
		CSVFormat format;
		if(t instanceof Map t1){
			List<String> keys = new ArrayList<>(t1.keySet());
			String[] strings = new String[keys.size()];
			format = CSVFormat.DEFAULT.withHeader(keys.toArray(strings));
		}else{
			format = CSVFormat.DEFAULT.withHeader(getTitle(t));
		}
        try(
				FileOutputStream fos = new FileOutputStream(filePath);
				OutputStreamWriter oswriter =new OutputStreamWriter(fos, StandardCharsets.UTF_8);
				CSVPrinter printer = new CSVPrinter(oswriter,format)
        ) {
			if(t instanceof Map map){
				for(T t1 : info){
					List<Object> values = new ArrayList<>();
					for(int i=0;i<new ArrayList<String>(map.keySet()).size();i++){
						Object o = ((Map<?, ?>)t1).get(new ArrayList<String>(map.keySet()).get(i));
						values.add((null==o)?"":o.toString());
					}
					Object [] tmp = new String[values.size()];
					printer.printRecord(values.toArray(tmp));
				}
				printer.flush();
			}else{//如果是POJO 通过ExcelProp注解来确定导出的属性
				for(T t1 : info){
					printer.printRecord(getItemValue(t1));
				}
				printer.flush();
			}
        }catch(Exception e) {
        	BizLogger.error(e);
        }
	}

	@Override
	public <T extends BaseEntity> void exportFile(T t, String fileName,int index, int process) {
		try {
			if(index == 0) {//第一次进去 初始化csvPrinter
				CSVFormat csvFormat = CSVFormat.DEFAULT.withHeader(getTitle(t));
				osw = new OutputStreamWriter(new FileOutputStream(fileName,true), StandardCharsets.UTF_8);
				csvPrinter = new CSVPrinter(osw,csvFormat);
			}
			csvPrinter.printRecord(getItemValue(t));
		}catch(Exception e) {
			BizLogger.error(e);
		}finally {
			if(100==process) {
				if(null != csvPrinter) {
					try {
						csvPrinter.flush();
						csvPrinter.close();
					}catch(Exception e) {
						BizLogger.error(e);
					}
				}
				if(null != osw) {
					try {
						osw.close();
					} catch (IOException e) {
						BizLogger.error(e);
					}
				}
			}
		}
	}
}
